/*
Copyright 2024 - 2025 Zen HuiFer

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"context"
	"encoding/json"
	"strings"

	"go.uber.org/zap"
)

// AddNoUseConfig 将不使用的MQTT配置信息存储到Redis中
//
// 参数：
//
//   - config MqttConfig  MQTT配置信息
//   - body []byte  待存储的字节数组
//
// 返回值：
//
//	无
func AddNoUseConfig(config MqttConfig, body []byte) {

	zap.S().Infof("AddNoUseConfig 开始, config = %v, body = %v", config, string(body))
	globalRedisClient.HSet(context.Background(), "mqtt_config:no", config.ClientId, body)
}

// GetNoUseConfig 从Redis中获取不使用的MQTT配置信息列表
//
// 返回值：
//
//   - []string  包含不使用MQTT配置信息的字符串切片
func GetNoUseConfig() []string {
	var noUseConfigs []string
	for _, s2 := range globalRedisClient.HGetAll(context.Background(), "mqtt_config:no").Val() {

		noUseConfigs = append(noUseConfigs, s2)
	}
	return noUseConfigs
}

// RemoveNoUseConfig 从Redis中删除不使用的MQTT配置信息
//
// 参数：
//
//   - config MqttConfig  MQTT配置信息
//
// 返回值：
//
//	无
func RemoveNoUseConfig(config MqttConfig) {
	zap.S().Infof("RemoveNoUseConfig 开始, config = %v", config)
	globalRedisClient.HDel(context.Background(), "mqtt_config:no", config.ClientId)
}

// AddUseConfig 将MQTT配置信息存储到Redis中
//
// 参数：
//
//   - config MqttConfig  MQTT配置信息
//
// 返回值：
//
//	无
func AddUseConfig(config MqttConfig) {
	zap.S().Infof("AddUseConfig 开始, config = %v", config)
	jsonStr, err := json.Marshal(config)
	if err != nil {
		panic(err)
	}
	globalRedisClient.HSet(context.Background(), "mqtt_config:use", config.ClientId, jsonStr)
}

// GetUseConfig 函数从Redis中获取已使用的MQTT配置信息
//
// 参数：
//
//   - client_id string - MQTT客户端ID
//
// 返回值：
//
//   - string  对应的MQTT配置信息
func GetUseConfig(clientId string) string {
	zap.S().Infof("GetUseConfig 开始, clientId = %v", clientId)
	return globalRedisClient.HGet(context.Background(), "mqtt_config:use", clientId).Val()
}

// GetNoUseConfigById 根据MQTT客户端ID获取不使用的MQTT配置信息
//
// 参数：
//
//   - client_id string - MQTT客户端ID
//
// 返回值：
//
//   - string  对应的不使用的MQTT配置信息
func GetNoUseConfigById(clientId string) string {
	zap.S().Infof("GetNoUseConfigById 开始, clientId = %v", clientId)
	return globalRedisClient.HGet(context.Background(), "mqtt_config:no", clientId).Val()
}

// RemoveUseConfig 从Redis中删除已使用的MQTT配置信息
//
// 参数：
//
//   - config MqttConfig - 待删除的MQTT配置信息
//
// 返回值：
//
//	无
func RemoveUseConfig(config MqttConfig) {
	zap.S().Infof("RemoveUseConfig 开始, config = %v", config)
	globalRedisClient.HDel(context.Background(), "mqtt_config:use", config.ClientId)
}

// CheckHasConfig 检查Redis中是否存在已使用的MQTT配置信息
//
// 参数：
//
//   - config MqttConfig - 待检查的MQTT配置信息
//
// 返回值：
//
//	bool - 若Redis中存在该配置信息则返回true，否则返回false
func CheckHasConfig(config MqttConfig) bool {
	zap.S().Infof("CheckHasConfig 开始, config = %v", config)
	return globalRedisClient.HExists(context.Background(), "mqtt_config:use", config.ClientId).Val()
}

// BindNode 函数用于将MQTT客户端绑定到指定节点
//
// 参数：
//
//   - config MqttConfig - MQTT配置信息
//   - node_name string - 节点名称
//
// 返回值：
//
//	无
func BindNode(config MqttConfig, nodeName string) {
	zap.S().Infof("BindNode 开始, config = %v, nodeName = %v", config, nodeName)
	globalRedisClient.SAdd(context.Background(), "node_bind:"+nodeName, config.ClientId)

	RemoveNoUseConfig(config)
	AddUseConfig(config)

}

// RemoveBindNode 函数用于从指定节点解绑MQTT客户端
//
// 参数：
//
//   - client_id string - MQTT客户端ID
//   - node_name string - 节点名称
//
// 返回值：
//
//	无
func RemoveBindNode(clientId string, nodeName string) {
	zap.S().Infof("RemoveBindNode 开始, clientId = %v, nodeName = %v", clientId, nodeName)
	globalRedisClient.SRem(context.Background(), "node_bind:"+nodeName, 0, clientId)

	configStr := GetUseConfig(clientId)
	var config MqttConfig
	var byt = []byte(configStr)

	err := json.Unmarshal(byt, &config)
	if err != nil {
		zap.S().Error("Error unmarshalling JSON:", err)
		return
	}

	RemoveUseConfig(config)
	AddNoUseConfig(config, byt)
}

// GetBindClientId 函数用于获取指定节点下所有绑定的MQTT客户端ID列表
//
// 参数：
//
//   - node_name string - 节点名称
//
// 返回值：
//
//   - []string  包含所有绑定在该节点下的MQTT客户端ID的字符串切片
func GetBindClientId(nodeName string) []string {
	zap.S().Infof("GetBindClientId 开始, nodeName = %v", nodeName)
	return globalRedisClient.SMembers(context.Background(), "node_bind:"+nodeName).Val()

}

func GetAllMqttConfigUsing() []MqttConfig {
	val := globalRedisClient.HGetAll(context.Background(), "mqtt_config:use").Val()
	var v []MqttConfig
	for _, s := range val {
		var config MqttConfig
		bytes := []byte(s)

		json.Unmarshal(bytes, &config)
		v = append(v, config)
	}
	return v
}

func GetAllNodeBind() []string {
	val := globalRedisClient.Keys(context.Background(), "node_bind:*").Val()
	var v []string
	for _, s := range val {
		i := globalRedisClient.SMembers(context.Background(), s).Val()
		for _, s2 := range i {
			v = append(v, s2)
		}
	}
	return v

}
func CheckMqttConfigIsUsingAndMove(ND string) {
	zap.S().Debugf("CheckMqttConfigIsUsingAndMove 开始")
	using := GetAllMqttConfigUsing()
	bind := GetBindClientId(ND)


	for _, s := range bind {
		CheckUsing(using, s)
	}

	for _, config := range using {
		if !StringInSlice(bind,config.ClientId){
			marshal, _ := json.Marshal(config)

			RemoveUseConfig(config)
			AddNoUseConfig(config, marshal)
		}
	}
}
func CheckUsing(v []MqttConfig, id string) bool {
	for _, config := range v {
		if config.ClientId == id {
			RemoveUseConfig(config)
			marshal, err := json.Marshal(config)
			if err != nil {
			}
			AddNoUseConfig(config, marshal)

			return true
		}
	}
	return false
}
func StringInSlice(slice []string, str string) bool {
	for _, v := range slice {
		if v == str {
			return true
		}
	}
	return false
}

// FindMqttClientId 函数用于查找MQTT客户端ID所在的节点名称
//
// 参数：
//
//	mqtt_client_id string：待查找的MQTT客户端ID
//
// 返回值：
//
//	string：MQTT客户端ID所在的节点名称，若未找到则返回空字符串
func FindMqttClientId(mqttClientId string) string {
	zap.S().Infof("FindMqttClientId 开始, mqttClientId = %v", mqttClientId)

	background := context.Background()
	result, err := globalRedisClient.Keys(background, "node_bind:*").Result()
	if err != nil {
		zap.S().Errorf("Error: %+v", err)
	}
	for _, elm := range result {
		for _, storageMqttClientId := range globalRedisClient.SMembers(background, elm).Val() {
			if storageMqttClientId == mqttClientId {
				modifiedString := strings.Replace(elm, "node_bind:", "", -1)
				return modifiedString

			}

		}
	}
	return ""
}
